package com.example.demo.java8;

import java.sql.Array;
import java.util.*;
import java.util.concurrent.atomic.DoubleAccumulator;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @ClassName StreamTest2
 * @Description Stream API 的操作->规约，收集
 * @Author hly
 * @Date 2018\11\29 0029 10:56
 */
public class StreamTest2 {

    /**
     * 规约
     * reduce(T iden, BinaryOperator b) 可以将流中元素反复结合起来，得到一个值。 返回 T
     * reduce(BinaryOperator b) 可以将流中元素反复结合起来，得到一个值。 返回 Optional<T>
     */

    private static List<Employee> emps = null;

    static {
        emps = Arrays.asList(
                new Employee(001, "Emma", 41, 20000, "1"),
                new Employee(002, "Mary", 39, 18000, "1"),
                new Employee(003, "Allen", 33, 15000, "1"),
                new Employee(004, "Olivia", 52, 32000, "1"),
                new Employee(005, "Natasha", 27, 13000, "1"),
                new Employee(006, "Kevin", 25, 1000, "1"),
                new Employee(007, "Haivent", 25, 12000, "0")
        );
    }

    //测试规约
    public void test01(){
        Integer[] array = {1,2,3};
        // 所有整数累加和
        Integer reduce = Arrays.asList(array).stream()
                .reduce(0, (x,y)->x+y);
        System.out.println(reduce);
    }

    public void test02() {
        Optional<Integer> reduce = emps.stream()
                .map(Employee::getName)
                .flatMap(StreamTest2::filterCharacter)
                .map((e)->{
                    if(e.equals('A')){
                        return 1;
                    }else{
                        return 0;
                    }
                })
                .reduce((a, b) -> Integer.sum(a, b));
        System.out.println(reduce.get());

    }

    private static Stream<Character> filterCharacter(String str){
        List<Character> list = new ArrayList<>();

        for (Character ch : str.toCharArray()) {
            list.add(ch);
        }
        return list.stream();
    }

    /**
     * 收集
     * collect(Collector c) 将流转换为其他形式。接收一个 Collector接口的实现，用于给Stream中元素做汇总的方法。
     Collector 接口中方法的实现决定了如何对流执行收集操作(如收集到 List、 Set、 Map)。但是 Collectors 实用类提供了很多静态方法，可以方便地创建常见收集器实例， 具体方法与实例如下：
     方法与实例：

     toList
     List<T> 把流中元素收集到List
     toSet
     Set<T> 把流中元素收集到Set
     toCollection
     Collection<T> 把流中元素收集到创建的集合
     counting
     Long 计算流中元素的个数
     summingInt
     Integer 对流中元素的整数属性求和
     averagingInt
     Double 计算流中元素Integer属性的平均值
     summarizingInt
     IntSummaryStatistics 收集流中Integer属性的统计值。如：平均值
     joining
     String 连接流中每个字符串
     maxBy
     Optional<T> 根据比较器选择最大值
     minBy
     Optional<T> 根据比较器选择最小值
     reducing
     归约产生的类型 从一个作为累加器的初始值开始，利用BinaryOperator与流中元素逐个结合，从而归约成单个值
     collectingAndThen
     转换函数返回的类型 包裹另一个收集器，对其结果转换函数
     groupingBy
     Map<K, List<T>> 根据某属性值对流分组，属性为K，结果为V
     partitioningBy
     Map<Boolean, List<T>> 根据true或false进行分区

     *
     */

    //测试收集 收集到集合
    public void test03() {
        List<String> collect = emps.stream()
                .map(Employee::getName)
                .collect(Collectors.toList());
        collect.forEach(System.out::println);

        System.out.println();
        Set<String> collect2 = emps.stream()
                .map(Employee::getName)
                .collect(Collectors.toSet());
        collect2.forEach(System.out::println);

        System.out.println();
        ArrayList<String> collect3 = emps.stream()
                .map(Employee::getName)
                .collect(Collectors.toCollection(ArrayList::new));
        collect3.forEach(System.out::println);
    }

    // 对流中元素进行计算
    public void test04(){
        Long collect = emps.stream()
                .collect(Collectors.counting());
        System.out.println("总员工数："+collect);

        Double collect2 = emps.stream()
                .collect(Collectors.summingDouble(Employee::getSalary));
        System.out.println("\n每月应发薪资总额："+collect2);

        Double collect3 = emps.stream()
                .collect(Collectors.averagingDouble(Employee::getSalary));
        System.out.println("\n员工平均月薪："+collect3);

        DoubleSummaryStatistics collect4 = emps.stream()
                .collect(Collectors.summarizingDouble(Employee::getSalary));
        System.out.println("\n员工中最低薪资为："+collect4.getMin());


//
//        Optional<Double> collect6 = emps.stream()
//                .map(Employee::getSalary)
//                .collect(Collectors.minBy(Double::compare));
//        System.out.println("\n员工中薪资最低为："+collect6.get());
//
//        Optional<Double> collect7 = emps.stream()
//                .map(Employee::getSalary)
//                .collect(Collectors.reducing(Double::sum));
//        System.out.println("\n员工每月薪资总共为："+collect7.get());



    }
    //将多个字符串连接成一个字符串
    public void test05(){
        String collect = emps.stream()
                .map(Employee::getName)
                .collect(Collectors.joining("-"));
        System.out.println(collect);
    }

    //对类型转换为集合后，返回集合大小
    public void test06(){
        Integer collect = emps.stream()
                .collect(Collectors.collectingAndThen(Collectors.toList(), List::size));
        System.out.println(collect);
    }

    //单级分组
    public void test07(){
        Map<String, List<Employee>> collect = emps.stream()
                .collect(Collectors.groupingBy(Employee::getState));
        System.out.println(collect);
    }

    //多级分组
    public void test08(){
        emps.stream().collect(Collectors.groupingBy((e) -> {
            if (e.getState().equals("0")){
                return "0";
            }else {
                return "1";
            }
        },Collectors.groupingBy((e) -> {
            if(e.getSalary() > 10000){
                        return "大于 15000";
                    }else if (e.getSalary() > 20000){
                        return "大于 20000";
                    }else{
                        return "大于25000";
                    }
        })));
//        Map<String, Map<String, List<Employee>>> collect = emps.stream()
//                .collect(Collectors.groupingBy((e)->{
//                    if(e.getState() .equals("0")){
//                        return "空闲";
//                    }else{
//                        return "繁忙";
//                    }
//                }, Collectors.groupingBy((e)->{
//                    if(e.getSalary() > 10000){
//                        return "大于 15000";
//                    }else if (e.getSalary() > 20000){
//                        return "大于 20000";
//                    }else{
//                        return "大于25000";
//                    }
//                })));
//        System.out.println(collect);
    }


    //根据员工状态进行分区
    public void test09(){
        Map<Boolean, List<Employee>> collect = emps.stream()
                .collect(Collectors.partitioningBy((e)->e.getState() == "0"));
        System.out.println(collect);
    }


    public static void main(String[] args) {
        StreamTest2 test2 = new StreamTest2();
//        test2.test01();
//        test2.test02();
//        test2.test03();
//        test2.test04();
//        test2.test05();
//        test2.test06();
//        test2.test07();
//        test2.test08();
        test2.test09();
    }






}
